/*
 * @Description: 页面消息提示
 * @Autor: HuiSir<273250950@qq.com>
 * @Date: 2023-03-27 22:27:51
 * @LastEditTime: 2023-03-28 00:07:36
 */

interface IHTMLOptions {
  content: string; // 这里支持content为html字符串
  type?: "error" | "success" | "info" | "warning" | "loading";
  duration?: number; // 延时关闭，为0时不关闭（需要手动关闭）
  showClose?: boolean; // 显示关闭按钮
}

/**
 * 使用
 *  abc('示例消息！')
 *  abc('示例消息！', 2000)
 *  abc('示例消息！', 0)
 *  abc({content:'示例消息！'}, 2000)
 *  abc({content:'示例消息！', type:'error', duration:2000, showClose:true })
 *  abc({content:'示例消息！', type:'error', duration:0 })
 *  abc.success('示例消息！')
 *  abc.error('示例消息！', 2000)
 */
class PageMessage {
  id: string;

  private msgEl: HTMLDivElement;
  private options: IHTMLOptions;
  private transitionDuration: number = 300;
  private defaultDuration: number = 2000;
  private msgOutBox: any;

  constructor(
    arg1: IHTMLOptions | IHTMLOptions["content"],
    arg2?: IHTMLOptions["duration"]
  ) {
    const duration =
      arg2 ??
      (typeof arg1 === "string"
        ? this.defaultDuration
        : arg1.duration ?? this.defaultDuration);

    this.options = {
      content: typeof arg1 === "string" ? arg1 : arg1.content,
      type: typeof arg1 === "string" ? "info" : arg1.type ?? "info",
      duration,
      showClose: typeof arg1 === "string" ? false : arg1.showClose ?? false,
    };

    this.id = Date.now().toString();
    this.msgEl = document.createElement("div");
    this.msgEl.setAttribute("data-id", this.id);
    this.msgEl.className = "gxh-page-message";
    this.msgEl.innerHTML = this.getHTML();
    this.options.showClose && this.msgEl.append(this.createCloseBtnEl());

    // 启用
    this.open();
  }

  /**
   * 启动、延时关闭
   * @returns
   */
  private open() {
    // 插入样式，这里需要判断是否已插入样式，只插入一次
    if (!document.head.querySelector('style[data-type="pageMessage"]')) {
      const styleEl = document.createElement("style");
      styleEl.setAttribute("type", "text/css");
      styleEl.setAttribute("data-type", "pageMessage");
      styleEl.innerText = this.getCss();
      document.head.append(styleEl);
    }

    // 外层盒子, 这里需要判断是否已插入外层盒子，只插入一次
    this.msgOutBox = document.body.querySelector(
      '.gxh-page-message-box[data-type="pageMessage"]'
    );

    if (!this.msgOutBox) {
      this.msgOutBox = document.createElement("div");
      this.msgOutBox.className = "gxh-page-message-box";
      this.msgOutBox.setAttribute("data-type", "pageMessage");
      document.body.append(this.msgOutBox);
    }

    // 插入当前msg
    this.msgOutBox.append(this.msgEl);

    // 启动
    setTimeout(() => (this.msgEl.className = "gxh-page-message gxh-pm-start"));

    // 当延时关闭设为0毫秒时，不自动关闭，这里需要手动关闭（显示关闭按钮或使用close方法）
    if (this.options.duration === 0) {
      return;
    }

    const t1 = setTimeout(() => {
      this.close();
      clearTimeout(t1);
    }, this.options.duration);
  }

  /**
   * 移除
   */
  public close() {
    this.msgEl.className = "gxh-page-message gxh-pm-finish";
    const t2 = setTimeout(() => {
      this.msgOutBox.removeChild(this.msgEl);
      clearTimeout(t2);
    }, this.transitionDuration + 100);
  }

  /**
   * 标签拼接
   * @returns string
   */
  private getHTML(): string {
    const icons = {
      error: `<svg focusable="false" t="1679992994290" class="gxh-pm-error-icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6734" width="1.2em" height="1.2em"><path d="M549.044706 512l166.189176-166.249412a26.383059 26.383059 0 0 0 0-36.98447 26.383059 26.383059 0 0 0-37.044706 0L512 475.015529l-166.249412-166.249411a26.383059 26.383059 0 0 0-36.98447 0 26.383059 26.383059 0 0 0 0 37.044706L475.015529 512l-166.249411 166.249412a26.383059 26.383059 0 0 0 0 36.98447 26.383059 26.383059 0 0 0 37.044706 0L512 548.984471l166.249412 166.249411a26.383059 26.383059 0 0 0 36.98447 0 26.383059 26.383059 0 0 0 0-37.044706L548.984471 512zM512 1024a512 512 0 1 1 0-1024 512 512 0 0 1 0 1024z" fill="#E84335" p-id="6735"></path></svg>`,
      success: `<svg focusable="false" t="1679992863046" class="gxh-pm-success-icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2764" width="1.2em" height="1.2em"><path d="M874.119618 149.859922A510.816461 510.816461 0 0 0 511.997 0.00208a509.910462 509.910462 0 0 0-362.119618 149.857842c-199.817789 199.679789-199.817789 524.581447 0 724.260236a509.969462 509.969462 0 0 0 362.119618 149.857842A508.872463 508.872463 0 0 0 874.119618 874.120158c199.836789-199.679789 199.836789-524.581447 0-724.260236zM814.94268 378.210681L470.999043 744.132295a15.359984 15.359984 0 0 1-5.887994 4.095996c-1.751998 1.180999-2.913997 2.362998-5.276994 2.913997a34.499964 34.499964 0 0 1-13.469986 2.914997 45.547952 45.547952 0 0 1-12.897986-2.303998l-4.095996-2.363997a45.291952 45.291952 0 0 1-7.009992-4.095996l-196.902793-193.789796a34.126964 34.126964 0 0 1-10.555989-25.186973c0-9.37399 3.583996-18.74698 9.98399-25.186974a36.429962 36.429962 0 0 1 50.372947 0l169.98382 167.423824L763.389735 330.220732a37.059961 37.059961 0 0 1 50.371947-1.732998 33.647965 33.647965 0 0 1 11.165988 25.186973 35.544963 35.544963 0 0 1-9.98399 24.575974v-0.04z m0 0" fill="#52C41A" p-id="2765"></path></svg>`,
      info: `<svg focusable="false" t="1679993064292" class="gxh-pm-info-icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7931" width="1.2em" height="1.2em"><path d="M512 505.281561m-499.512195 0a499.512195 499.512195 0 1 0 999.02439 0 499.512195 499.512195 0 1 0-999.02439 0Z" fill="#2196F3" p-id="7932"></path><path d="M464.421463 457.703024h95.157074v261.644488h-95.157074z" fill="#FFFFFF" p-id="7933"></path><path d="M512 326.88078m-59.466927 0a59.466927 59.466927 0 1 0 118.933854 0 59.466927 59.466927 0 1 0-118.933854 0Z" fill="#FFFFFF" p-id="7934"></path></svg>`,
      warning: `<svg focusable="false" t="1679993136335" class="gxh-pm-warning-icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="14476" width="1.2em" height="1.2em"><path d="M512 1024C229.248 1024 0 794.752 0 512S229.248 0 512 0s512 229.248 512 512-229.248 512-512 512z m-2.346667-210.901333a64 64 0 1 0 0-128 64 64 0 0 0 0 128zM509.482667 213.333333a82.816 82.816 0 0 0-82.090667 93.610667l38.528 293.546667c2.944 22.4 22.016 39.168 44.629333 39.168a44.8 44.8 0 0 0 44.458667-39.168l37.034667-293.504A83.2 83.2 0 0 0 509.482667 213.333333z" fill="#F5A623" p-id="14477"></path></svg>`,
      loading: `<svg focusable="false" class="gxh-pm-loading-icon" width="1.2em" height="1.2em" viewBox="25 25 50 50"><circle class="path" cx="50" cy="50" r="20" fill="none"></circle></svg>`,
    };
    return `
            <div class="gxh-page-message-icon">${
              icons[this.options.type!]
            }</div>
            <div class="gxh-page-message-content">${this.options.content}</div>
        `;
  }

  /**
   * 创建关闭按钮元素
   * @returns HTMLDivElement
   */
  private createCloseBtnEl(): HTMLDivElement {
    const closeBtnEl = document.createElement("div");
    closeBtnEl.className = "gxh-page-message-close";
    closeBtnEl.innerHTML = `<svg focusable="false" class="close-icon" data-icon="close" width=".8em" height=".8em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 00203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"></path></svg>`;
    // 点击关闭
    closeBtnEl.onclick = this.close.bind(this);
    return closeBtnEl;
  }

  /**
   * 样式拼接
   * @returns string
   */
  private getCss(): string {
    return `
            @keyframes=gxh-pm-loading-icon-anim{
              100% {
                transform: rotate(360deg);
              }
            }
            svg.gxh-pm-loading-icon {
              animation: gxh-pm-loading-icon-anim=1s=linear=infinite;
            }
            svg.gxh-pm-loading-icon>circle.path {
              stroke-dasharray: 90,150;
              stroke-dashoffset: 0;
              stroke-width: 4px;
              stroke: #409eff;
              stroke-linecap: round;
            }
            .gxh-page-message-box{
              position:fixed;
              top:0;
              width:100%;
              z-index:9999;
            }
            .gxh-page-message{
              font-size:14px;
              color: #000000d9;
              line-height:1.2;
              padding:10px=16px;
              background:#fff;
              max-width:70%;
              margin-top:0;
              margin-left:50%;
              opacity:0;
              transition:all=${this.transitionDuration}ms=ease-in-out;
              transform:translateX(-50%);
              display:inline-flex;
              align-items:center;
              border-radius: 3px;
              box-shadow: 0=3px=6px=-4px=#0000001f, 0=6px=16px=#00000014, 0=9px=28px=8px=#0000000d;
            }
            .gxh-page-message-icon,.gxh-page-message-close{
              display:flex;
              align-items:center;
              color:#00000073;
              cursor: pointer;
            }
            .gxh-page-message-content{
              margin:0=.6em;
            }
            .gxh-page-message.gxh-pm-start{
              margin-top:18px;
              opacity:100;
            }
        `.replace(/\s|=/g, (e) => {
      return e === "=" ? " " : "";
    });
  }
}

/**
 * 实例化
 * @param arg1 消息内容或配置项
 * @param arg2 延时关闭时间（毫秒）
 * @returns PageMessage
 */
function Instance(arg1: string | IHTMLOptions, arg2?: number) {
  return new PageMessage(arg1, arg2);
}

/**
 * 成功消息提示
 * @param content 消息内容，支持html标签
 * @param duration 延时关闭毫秒数，为0需手动关闭
 * @returns PageMessage
 */
Instance.success = (content: string, duration?: number) =>
  Instance({
    content,
    duration,
    type: "success",
  });
/**
 * 失败消息提示
 * @param content 消息内容，支持html标签
 * @param duration 延时关闭毫秒数，为0需手动关闭
 * @returns PageMessage
 */
Instance.error = (content: string, duration?: number) =>
  Instance({
    content,
    duration,
    type: "error",
  });
/**
 * 普通消息提示
 * @param content 消息内容，支持html标签
 * @param duration 延时关闭毫秒数，为0需手动关闭
 * @returns PageMessage
 */
Instance.info = (content: string, duration?: number) =>
  Instance({
    content,
    duration,
    type: "info",
  });
/**
 * 告警消息提示
 * @param content 消息内容，支持html标签
 * @param duration 延时关闭毫秒数，为0需手动关闭
 * @returns PageMessage
 */
Instance.warning = (content: string, duration?: number) =>
  Instance({
    content,
    duration,
    type: "warning",
  });

/**
 * 简易loading（无遮罩）
 * @param content 默认为`加载中...`
 * @param duration 延时关闭毫秒数，为0需手动关闭
 * @returns PageMessage
 */
Instance.loading = (content: string = "加载中...") =>
  Instance({
    content,
    duration: 0,
    type: "loading",
  });

export default Instance;
